#include "mloop.h"
#include <sys/times.h>

void init(char *pdbfile, int nseg, char loopseq[MAX_SEGMENT][20], int *begin, int *end)
{
	init_Ramachandran_plot ();
	build_loops (pdbfile, nseg, loopseq, begin, end);
	build_table ();
	read_environatom (pdbfile, nseg, begin, end);
	grid_mapping ();
	grid2_mapping ();
	read_pmfscore ();
}

int main(int argc, char *argv[])
{
	char pdbfile[80], loopseq[MAX_SEGMENT][20], filename[80];
	int nseg = 1, begin[MAX_SEGMENT], end[MAX_SEGMENT];
	int max_output = 0;
	float threshold, threshold_step;
	int argc0 = 1, flag = 0, i;
	long int random_seed = 19790912;
	struct tms CPU_time;

	mode = -1; nsaves = nsaves2 = loop_length = 0;
	while (argc0 < argc)
	{
		char argline[256];
		strcpy (argline, argv[argc0++]);
		if (!strcmp (argline, "-s"))
		{
			strcpy (pdbfile, argv[argc0++]);
			flag++;
		}
		else if (!strcmp (argline, "-m"))
		{
			nseg = atoi (argv[argc0++]);
		}
		else if (!strcmp (argline, "-l"))
		{
			for (i = 0; i < nseg; i++)
			{
				strcpy (loopseq[i], argv[argc0++]);
			}
			flag++;
		}
		else if (!strcmp (argline, "-b"))
		{
			for (i = 0; i < nseg; i++)
				begin[i] = atoi (argv[argc0++]);
			flag++;
		}
		else if (!strcmp (argline, "-e"))
		{
			for (i = 0; i < nseg; i++)
			{
				end[i] = atoi (argv[argc0++]);
				if (i == 0 || loop_length < end[i] - begin[i] + 1)
					loop_length = end[i] - begin[i] + 1;
			}
			flag++;
		}
		else if (!strcmp (argline, "-c"))
		{
			mode = atoi(argv[argc0++]);
		}
		else if (!strcmp (argline, "-o"))
		{
			strcpy (filename, argv[argc0++]);
			flag++;
		}
		else if (!strcmp (argline, "-n"))
		{
			max_output = atoi (argv[argc0++]);
		}
		else if (!strcmp (argline, "-r"))
		{
			random_seed = atoi (argv[argc0++]);
		}
	}

	if (flag != 5)
	{
		printf ("Usage : %s -s pdbfile -m loop_num -l loopseq -b loop_begin -e loop_end -c calc_mode -o output_filename -r random_seed\n", argv[0]);
		exit(0);
	}

	if (max_output == 0)
	{
		max_output = 5000;
	}

	threshold = 0.25 * loop_length - 0.4;
	if (loop_length > 10)
	{
		//threshold = 0.3 * (loop_length - 3) - 0.1;
		threshold_step = 0.3;
	}
	else if (loop_length > 6)
	{
		//threshold = 0.25 * (loop_length - 2);
		threshold_step = 0.25;
	}
	else
	{
		//threshold = 0.20 * (loop_length - 1);
		threshold_step = 0.2;
	}

	if (mode == -1)
	{
		//mode = 2;
		if (loop_length < 10)
			mode = 0;
		else
			mode = 1;
	}

	printf ("Random Seed: %ld\n", random_seed);
	if (mode == 0)
		printf ("Sidechain Modelling: Enabled\n");
	else if (mode == 1)
		printf ("Sidechain Modelling: Disabled\n");
	else if (mode == 2)
		printf ("Sidechain Modelling: Smart Mode\n");
	printf ("Maximum Output: %d\n", max_output);

	candidate = (struct candidate *) calloc (max_output + 1, sizeof (struct candidate));
	candidate2 = (struct candidate *) calloc (max_output + 1, sizeof (struct candidate));
	repr_num = (int *) calloc (max_output, sizeof (int));
	srand48 (random_seed);
	init (pdbfile, nseg, loopseq, begin, end);
	
#ifdef DEBUG
	if (calc_energy1 (&ref) < 0)
		printf ("ERROR: Loop coordinates of crystal structure are out of range.\n");
	else
	{
		calc_pmfscore (&ref);
		printf ("Experimental Structure: E1 %f\tE2 %f PMF %f\n", ref.energy1, ref.energy2, ref.energypmf);
	}
#endif

	numofsamples = 0;
	//packing = 1;
	reinit (&current[0]);
	flag = mmc (max_output * 0.6, threshold);

	if (flag == 0)
		threshold += threshold_step;
	reinit (&current[0]);
	flag = mmc (max_output * 0.8, threshold);

	if (flag == 0)
		threshold += threshold_step;
	reinit (&current[0]);
	mmc (max_output, threshold);
	//randomwalk (max_output, threshold);
	loop_output (filename);
	times (&CPU_time);
	printf ("User Time %ld\n", CPU_time.tms_utime / 100);
}
